package luc.hci.emotext.communication;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;

import luc.hci.emotext.interfaces.Manager;
import luc.hci.emotext.interfaces.SocketerInterface;

import android.util.Log;

public class Socketer implements SocketerInterface
{
	// Here put IP_Address
	//private static final String AUTHENTICATION_SERVER_ADDRESS = "http://192.168.1.148/AndroidChatterDatabase/";
	private static final String AUTHENTICATION_SERVER_ADDRESS = "http://192.168.43.245/emotext/"; //T-Mobile Hotspot
    //private static final String AUTHENTICATION_SERVER_ADDRESS = "http://216.124.114.99/emotext/"; // Work Server

	private int listeningPort = 0;

	private static final String HTTP_REQUEST_FAILED = null;

	private HashMap< InetAddress, Socket > sockets = new HashMap< InetAddress, Socket >( );

	private ServerSocket serverSocket = null;

	private boolean listening;

	private class ReceiveConnection extends Thread
	{
		Socket clientSocket = null;

		public ReceiveConnection( Socket socket )
		{
			this.clientSocket = socket;
			Socketer.this.sockets.put( socket.getInetAddress( ), socket );
		}

		@Override
		public void run( )
		{
			try
			{
				BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream( ) ) );
				String inputLine;

				while ( ( inputLine = in.readLine( ) ) != null )
				{
					if ( inputLine.equals( "exit" ) )
					{
						clientSocket.shutdownInput( );
						clientSocket.shutdownOutput( );
						clientSocket.close( );
						Socketer.this.sockets.remove( clientSocket.getInetAddress( ) );
					}
				}

			}
			catch ( IOException e )
			{
				Log.e( "ReceiveConnection.run ", "When receiving connection" );
			}
		}
	}

	public Socketer( Manager appManager )
	{
	}

	public String sendHttpRequest( String params )
	{
		URL url;
		String result = new String( );
		try
		{
			url = new URL( AUTHENTICATION_SERVER_ADDRESS );
			HttpURLConnection connection;
			connection = ( HttpURLConnection ) url.openConnection( );
			connection.setDoOutput( true );

			PrintWriter out = new PrintWriter( connection.getOutputStream( ) );

			out.println( params );
			out.close( );

			BufferedReader in = new BufferedReader( new InputStreamReader( connection.getInputStream( ) ) );
			String inputLine;

			while ( ( inputLine = in.readLine( ) ) != null )
			{
				result = result.concat( inputLine );
			}
			in.close( );
		}
		catch ( MalformedURLException e )
		{
			Log.e( "sendHttpRequest ", "MalformedURLException" );
			e.printStackTrace( );
		}
		catch ( IOException e )
		{
			Log.e( "sendHttpRequest ", "IOException" );
			e.printStackTrace( );
		}

		if ( result.length( ) == 0 )
		{
			result = HTTP_REQUEST_FAILED;
		}

		return result;

	}

	public int startListening( int portNo )
	{
		listening = true;

		try
		{
			serverSocket = new ServerSocket( portNo );
			this.listeningPort = portNo;
		}
		catch ( IOException e )
		{
			Log.e( "startListening.serverSocket ", "IOException" );
			this.listeningPort = 0;
			return 0;
		}

		while ( listening )
		{
			try
			{
				new ReceiveConnection( serverSocket.accept( ) ).start( );
			}
			catch ( IOException e )
			{
				Log.e( "startListening.receiveConnection ", "IOException" );
				return 2;
			}
		}

		try
		{
			serverSocket.close( );
		}
		catch ( IOException e )
		{
			Log.e( "Exception server socket", "Exception when closing server socket" );
			return 3;
		}

		return 1;
	}

	public void stopListening( )
	{
		this.listening = false;
	}

	public void exit( )
	{
		for ( Iterator< Socket > iterator = sockets.values( ).iterator( ); iterator.hasNext( ); )
		{
			Socket socket = ( Socket ) iterator.next( );
			try
			{
				socket.shutdownInput( );
				socket.shutdownOutput( );
				socket.close( );
			}
			catch ( IOException e )
			{
			}
		}

		sockets.clear( );
		this.stopListening( );
	}

	public int getListeningPort( )
	{

		return this.listeningPort;
	}
}